#include "key.h"

/*需定义按键结构体并初始化*/
KEY_t key[KEY_MAX] =
{
    [0] = {KEY_UP, FREE_EVENT, MS_TO_CYCLE(100), MS_TO_CYCLE(1000), 0, 1, KEY1_GPIO, KEY1_PIN},
    [1] = {KEY_UP, FREE_EVENT, MS_TO_CYCLE(100), MS_TO_CYCLE(1000), 0, 1, KEY2_GPIO, KEY2_PIN},
    [2] = {KEY_UP, FREE_EVENT, MS_TO_CYCLE(100), MS_TO_CYCLE(1000), 0, 1, KEY3_GPIO, KEY3_PIN},
    [3] = {KEY_UP, FREE_EVENT, MS_TO_CYCLE(100), MS_TO_CYCLE(1000), 0, 1, KEY4_GPIO, KEY4_PIN},
    [4] = {KEY_UP, FREE_EVENT, MS_TO_CYCLE(100), MS_TO_CYCLE(1000), 0, 1, KEY5_GPIO, KEY5_PIN},
    [5] = {KEY_UP, FREE_EVENT, MS_TO_CYCLE(100), MS_TO_CYCLE(1000), 0, 1, KEY6_GPIO, KEY6_PIN},
    [6] = {KEY_UP, FREE_EVENT, MS_TO_CYCLE(100), MS_TO_CYCLE(1000), 0, 1, KEY7_GPIO, KEY7_PIN},
    [7] = {KEY_UP, FREE_EVENT, MS_TO_CYCLE(100), MS_TO_CYCLE(1000), 0, 1, KEY8_GPIO, KEY8_PIN},
};

/*
功能：对按键对应的GPIO进行初始化
参数：无
返回：无
备注：
*/
void KEY_Init(void)
{
    /* enable PORTB module*/
    CLK_ModuleSrc(CLK_PORTB, CLK_SRC_OSC40M);
    SYSCTRL_EnableModule(SYSCTRL_PORTB);
    CLK_ModuleSrc(CLK_PORTC, CLK_SRC_OSC40M);
    SYSCTRL_EnableModule(SYSCTRL_PORTC);
    CLK_ModuleSrc(CLK_PORTD, CLK_SRC_OSC40M);
    SYSCTRL_EnableModule(SYSCTRL_PORTD);
    CLK_ModuleSrc(CLK_PORTE, CLK_SRC_OSC40M);
    SYSCTRL_EnableModule(SYSCTRL_PORTE);

    /* enable GPIO module*/
    SYSCTRL_EnableModule(SYSCTRL_GPIO);

    /* set pin as GPIO*/
    PORT_PinmuxConfig(KEY1_GPIO, KEY1_PIN, PTE8_GPIO);   
    PORT_PinmuxConfig(KEY2_GPIO, KEY2_PIN, PTB5_GPIO);   
    PORT_PinmuxConfig(KEY3_GPIO, KEY3_PIN, PTB4_GPIO);      
    PORT_PinmuxConfig(KEY4_GPIO, KEY4_PIN, PTC3_GPIO);   
    PORT_PinmuxConfig(KEY5_GPIO, KEY5_PIN, PTC2_GPIO);   
    PORT_PinmuxConfig(KEY6_GPIO, KEY6_PIN, PTD5_GPIO);  
    PORT_PinmuxConfig(KEY7_GPIO, KEY7_PIN, PTC1_GPIO);   
    PORT_PinmuxConfig(KEY8_GPIO, KEY8_PIN, PTC16_GPIO);  
  
    GPIO_SetPinDir(KEY1_GPIO, KEY1_PIN, GPIO_INPUT);    
    GPIO_SetPinDir(KEY2_GPIO, KEY2_PIN, GPIO_INPUT);  
    GPIO_SetPinDir(KEY3_GPIO, KEY3_PIN, GPIO_INPUT);  
    GPIO_SetPinDir(KEY4_GPIO, KEY4_PIN, GPIO_INPUT);  
    GPIO_SetPinDir(KEY5_GPIO, KEY5_PIN, GPIO_INPUT);    
    GPIO_SetPinDir(KEY6_GPIO, KEY6_PIN, GPIO_INPUT);  
    GPIO_SetPinDir(KEY7_GPIO, KEY7_PIN, GPIO_INPUT);  
    GPIO_SetPinDir(KEY8_GPIO, KEY8_PIN, GPIO_INPUT); 
}

/*
功能：按键扫描，更新按键状态和事件
参数：无
返回：无
备注：发生按键事件后，事件变量更新，不会自动清零，新事件会覆盖旧事件
*/
void KEY_Scan(void)
{
    uint8_t value = 0;
    for (uint8_t i = 0; i < KEY_MAX; i++)
    {
        value = GPIO_ReadPinLevel(key[i].gpio, key[i].pin);
        switch (key[i].sta)
        {
        case KEY_UP:    
            key[i].cnt = 0; 
            key[i].event = FREE_EVENT;
            key[i].sta = (value == key[i].level) ? KEY_DOWM : KEY_UP; 
            break;
        case KEY_DOWM: 
            if(value == key[i].level) 
            {
                key[i].event = TRI_EVENT; 
                key[i].sta = KEY_HOLD;
            }
            else
            {
                key[i].event = FREE_EVENT; 
                key[i].sta = KEY_UP;                
            }
            break;
        case KEY_HOLD:  
            if(key[i].cnt < 0xff) key[i].cnt++; 
            if(key[i].cnt == key[i].long_cnt)
            {
                key[i].event = LONG_EVENT;
            }
            else if(key[i].cnt == key[i].short_cnt)
            {
                key[i].event = SHORT_EVENT;
            }
            key[i].sta = (value == key[i].level) ? KEY_HOLD : KEY_LOOSE; 
            break;
        case KEY_LOOSE: 
            if(value == key[i].level) 
            {
                key[i].sta = KEY_HOLD;
            }
            else
            {
                key[i].event = LOOSE_EVENT; 
                key[i].sta = KEY_UP;                
            }
            break;
        default: 
            break;
        }
    }
}
